#include <iostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
#include "Mutex.hpp"
using namespace mutexdouble;

/* 条件变量 */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
 
void *active(void *arg)
{
    std::string name = static_cast<const char*>(arg);
    while(true)
    {
        pthread_mutex_lock(&mutex);
        // 没有对于资源是否就绪的判定
        pthread_cond_wait(&cond, &mutex); // mutex??
        printf("%s is active!\n", name.c_str());
        pthread_mutex_unlock(&mutex);
    }
    
}
 
int main()
{
    pthread_t tid1, tid2, tid3;
 
    pthread_create(&tid1, nullptr, active, (void*)"thread-1");
    pthread_create(&tid2, nullptr, active, (void*)"thread-2");
    pthread_create(&tid3, nullptr, active, (void*)"thread-3");
 
    sleep(1);
    printf("Main thread ctrl begin...\n");
 
    while(true){
        printf("main wakeup thread...\n");
        pthread_cond_signal(&cond); // 一个一个唤醒
        // pthread_cond_broadcast(&cond); // 全部唤醒
        sleep(1);
    }
 
    pthread_join(tid1, nullptr);
    pthread_join(tid2, nullptr);
    pthread_join(tid3, nullptr);
 
    return 0;
}


#if 0
/* 抢票系统 */
int ticket = 1000; /* 票数 */
Mutex lock;
void *routine(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        {
            MutexGuard guard(lock);
            if (ticket > 0)
            {
                usleep(1000);
                std::cout << name << " Get a ticket, having: " << ticket << " leave" << std::endl;
                ticket--;
            }
            else
            {
                break;
            }
        }
    }
    return nullptr;
}

int main()
{
    pthread_t t1, t2, t3, t4;

    pthread_create(&t1, nullptr, routine, (void *)"thread-1");
    pthread_create(&t2, nullptr, routine, (void *)"thread-2");
    pthread_create(&t3, nullptr, routine, (void *)"thread-3");
    pthread_create(&t4, nullptr, routine, (void *)"thread-4");

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);

    return 0;
}
#endif

#if 0
/* 抢票系统 */
int ticket = 1000; /* 票数 */
/* 局部锁 */
pthread_mutex_t lock;
void *routine(void *args)
{
    std::string name = static_cast<const char*>(args);
    pthread_mutex_init(&lock, nullptr);
    while(true)
    {
        /* 加锁 */
        pthread_mutex_lock(&lock);
        if(ticket > 0)
        {
            usleep(1000);
            std::cout << name << " Get a ticket, having: " << ticket << " leave" << std::endl;
            ticket--;
            /* 解锁 */
            pthread_mutex_unlock(&lock);
        }
        else
        {
            /* 解锁 */
            pthread_mutex_unlock(&lock);
            break;
        }
    }
    return nullptr;
}

int main()
{
    pthread_t t1, t2, t3, t4;
    /* 初始化 */
    pthread_mutex_init(&lock, nullptr);
    pthread_create(&t1, nullptr, routine, (void*)"thread-1");
    pthread_create(&t2, nullptr, routine, (void*)"thread-2");
    pthread_create(&t3, nullptr, routine, (void*)"thread-3");
    pthread_create(&t4, nullptr, routine, (void*)"thread-4");

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);
    /* 销毁 */
    pthread_mutex_destroy(&lock);
    return 0;
}
#endif

#if 0
/* 抢票系统 */
int ticket = 1000; /* 票数 */
/* 全局锁 */
pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
void *routine(void *args)
{
    std::string name = static_cast<const char*>(args);
    while(true)
    {
        /* 加锁 */
        pthread_mutex_lock(&glock);
        if(ticket > 0)
        {
            usleep(1000);
            std::cout << name << " Get a ticket, having: " << ticket << " leave" << std::endl;
            ticket--;
            /* 解锁 */
            pthread_mutex_unlock(&glock);
        }
        else
        {
            /* 解锁 */
            pthread_mutex_unlock(&glock);
            break;
        }
    }
    return nullptr;
}

int main()
{
    pthread_t t1, t2, t3, t4;
    pthread_create(&t1, nullptr, routine, (void*)"thread-1");
    pthread_create(&t2, nullptr, routine, (void*)"thread-2");
    pthread_create(&t3, nullptr, routine, (void*)"thread-3");
    pthread_create(&t4, nullptr, routine, (void*)"thread-4");

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);
    return 0;
}
#endif